package com.berchen.test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;

/**
 * 自定义ClassLoader
 * 1、继承ClassLoader
 * 2、重写方法findClass
 *
 * JDK1.2 之前建议重写loadClass方法但是1.2之后建议重写findClass方法。
 * 如果没有太过于复杂的需求，可以直接继承URLClassLoader类。
 *
 * 打破双亲委派模型：继承ClassLoader，重写loadClass方法。（第一次打破）
 * 第二次打破：Service和Thread.setContextClassLoader()。
 *
 * JDK9引入模块系统后，类加载器的实现做了一次更新，当收到类加载请求的时候，会先判断该类在自定义模块中是否有定义，如果有定义就自己加载了，如果没有定义再委派给父类。
 */
public class ZdyClassLoader extends ClassLoader{

    private File classPathFile;
    public ZdyClassLoader() {
        String classPath=ZdyClassLoader.class.getResource("").getPath();
        this.classPathFile=new File(classPath);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        String className=ZdyClassLoader.class.getPackage().toString()+"."+name;
        if(classPathFile!=null){
            // 需要加载的类的具体class文件的路径
            File classFile=new File(classPathFile+File.separator+name+".class");
            if(classFile.exists()){
                FileInputStream fis=null;

                ByteArrayOutputStream bos=null;
                try{

                    fis=new FileInputStream(classFile);
                    byte[] bytes=new byte[4096];
                    bos=new ByteArrayOutputStream();
                    int len;
                    while((len=fis.read(bytes))!=-1){
                        bos.write(bytes,0,len);
                    }
                    /**
                     * 第一个参数 就是要加载的类的前限定类名 com/berchen/test/Test08
                     */
                    return defineClass(className.replace("package","").trim(),bos.toByteArray(),0,bos.size());
                }catch (Exception e){

                    System.out.println("---------系统异常");
                }finally {
                    try{

                        if(fis!=null){
                            fis.close();
                        }
                    }catch (Exception e){

                    }
                }
            }
        }
        throw new ClassNotFoundException(className+" not found");
    }
}
